<template>
  <div class="upload-button">
    <template v-if="multiple">
      <input
        ref="input"
        type="file"
        multiple="multiple"
        :accept="acceptType"
        @change="handleChange"
      />
    </template>
    <template v-else>
      <input
        ref="input"
        type="file"
        :accept="acceptType"
        @change="handleChange"
      />
    </template>
  </div>
</template>

<script>
import { reactive, ref } from '@vue/composition-api'
import { Message } from 'element-ui'
import { post } from 'axios' // 请求也是的，建议直接使用项目中已经封装好的请求函数来调接口。我这是自己搭建的练手的项目，就没去封装请求。
import commonApi from '@/api/modules/common' // 这个是接口地址，根据自己需求改。
const defaultType = [
  'bmp',
  'jpg',
  'png',
  'tif',
  'gif',
  'pcx',
  'tga',
  'exif',
  'fpx',
  'svg',
  'psd',
  'cdr',
  'pcd',
  'dxf',
  'ufo',
  'eps',
  'ai',
  'raw',
  'WMF',
  'webp',
]
export default {
  props: {
    multiple: {
      // 是否多选
      type: Boolean,
      default: false,
    },
    acceptType: {
      // 文件类型
      type: String,
      default: 'image/*',
    },
    type: {
      // 限制上传文件类型
      type: String,
      default: undefined,
    },
    size: {
      // 限制上传文件尺寸
      type: String,
      default: undefined,
    },
    bulk: {
      // 限制上传文件大小
      type: Number,
      default: 0,
    },
  },
  emits: ['url'],
  setup(props, c) {
    const { bulk, type, size, multiple } = reactive(props)
    const uploading = ref(false)
    const input = ref(null)
    const url = ref(undefined)
    let uploadFiles = reactive([])

    const inputClick = () => {
      if (uploading.value) {
        return Message.warning('请等待前面的文件完成上传!')
      }
      return input.value.click()
    }

    const handleChange = ({ target }) => {
      if (multiple) uploadFiles = [...target.files]

      uploadFile(target.files[0])
      target.value = ''
    }

    const uploadFile = async (file) => {
      try {
        if (type) await detectorType(file)
        if (bulk) await detectorBulk(file)
        if (size) await detectorSize(file)

        uploading.value = true
        const fd = new FormData()
        url.value = commonApi.addUserEmoticon
        fd.append('file', file) // 可以通过这种形式，来传递其他项目中要传递的参数。
        const data = await post(url.value, fd, {
          headers: {
            'content-type': 'multipart/form-data',
          },
        })

        c.emit('url', data) // 将请求到的数据 抛出去
        uploaded(false)
      } catch (err) {
        uploaded(err)
      }
    }

    const detectorType = (file) => {
      return new Promise((resolve, reject) => {
        const sizeList = type.split(',')
        const fileSize = file.name.split('.')
        const fileExtension = fileSize[fileSize.length - 1].toLowerCase()
        if (!sizeList.includes(fileExtension)) {
          if (!defaultType.includes(fileExtension)) {
            Message.error('文件类型不对！')
          } else {
            Message.error('图片类型不对！')
          }
          reject(new Error())
        } else {
          resolve(true)
        }
      })
    }

    const detectorBulk = (file) => {
      return new Promise((resolve, reject) => {
        const fileSize = file.size / 1024 / 1024
        if (fileSize > bulk) {
          Message.error(`大小超出${bulk}M`)
          reject(new Error())
        } else {
          resolve(true)
        }
      })
    }

    const detectorSize = (file) => {
      return new Promise((resolve, reject) => {
        const image = new Image()
        const URL = window.URL || window.webkitURL

        image.onload = () => {
          const sizes = size.split(',')
          if (
            image.width === Number(sizes[0]) &&
            image.height === Number(sizes[1])
          ) {
            resolve(true)
          } else {
            Message.error({
              type: 'error',
              message: `请上传尺寸为 ${sizes.join(' x ')} 的图片`,
            })
            reject(new Error())
          }
        }
        image.src = URL.createObjectURL(file)
      })
    }

    const uploaded = (err, state = false) => {
      console.log('state', state)
      uploading.value = false
      if (!err) {
        if (multiple && uploadFiles.length > 1) {
          uploadFiles = uploadFiles.slice(1, uploadFiles.length - 1)
          uploadFile(uploadFiles[0])
        } else {
          Message.success('上传成功！')
        }
      }
    }

    return {
      input,
      inputClick,
      handleChange,
    }
  },
}
</script>

<style scoped lang="less"></style>
